/*
 * pcm.c
 *
 *  Created on: 2022年8月29日
 *      Author: pengkun.he
 */

#include "pcm.h"

const uint32_t TestGagNum = 1;

void *PcmAddr = NULL;

PCM_CB PCMCB[PCM_PORT_NUM];
/*****************************************************/
volatile unsigned long *pcm1_viraddr = NULL;
volatile unsigned long *pcm2_viraddr = NULL;
volatile unsigned long *pcm_reset_vir= NULL;

volatile unsigned long *pcm1_en = NULL;
volatile unsigned long *pcm2_en = NULL;

int axidma_cnt_init()
{
	pcm1_viraddr = axidma_cnt_mmap(pcm1_start_cnt_phy);
	pcm1_en = axidma_cnt_mmap(pcm1_en_phy);

	pcm2_viraddr = axidma_cnt_mmap(pcm2_start_cnt_phy);
	pcm2_en = axidma_cnt_mmap(pcm2_en_phy);

	pcm_reset_vir= axidma_cnt_mmap(pcm_reset_phy);

	if((pcm1_viraddr == NULL)||(pcm2_viraddr == NULL))
	{
		printf("pcm cnt reg mmap failed ! \n");
		return -1;
	}
	return 0;
}

void pcm_reset(void)
{
	*pcm_reset_vir = 0 ;
	usleep(1);
	*pcm_reset_vir = 1 ;
	usleep(1);
	*pcm_reset_vir = 0 ;
	usleep(1);
}

unsigned int get_axidma_cnt(unsigned char dma)
{
	if(dma == 1)
		return *pcm1_viraddr ;
	else if(dma == 2)
		return *pcm2_viraddr;
	else;

	return 0;
}

void en_pcm(int dma, int en)
{
	if(dma == 1)
		*pcm1_en = en ;
	else if(dma == 2)
		*pcm2_en = en ;
	else;
}

void pulse_flag(char channel)
{
	if(channel == 1)
	{
		en_pcm(1,0);
		en_pcm(1,1);
		en_pcm(1,0);
	}
	else if(channel == 2)
	{
		en_pcm(2,0);
		en_pcm(2,1);
		en_pcm(2,0);
	}
}

void *axidma_cnt_mmap(unsigned long addr)
{
	int fd = -1;
	return devm_map(addr, 1, &fd);
}

/****************************************************/
void PCM_Test_890(int num)
{
    int PcmHdl = -1;

    memset((void *)PCMCB, 0, sizeof(PCMCB));
    printf("sizeof(PCMCB)=%d\n", sizeof(PCMCB));

    if(PcmAddr == NULL)
    {
		PcmAddr = devm_map(PCM_MEM_BASE, PCM_MEM_LEN * PCM_PORT_NUM, &PcmHdl); //hpk *num
		if(PcmAddr == NULL)
		{
			printf("PCM mmap fail!\n");
			return;
		}
    }
//    PCMInit(pcm_0);
//    PCMInit(pcm_1);
    PCMCB[0].InitOK = PCM_ENABLE_VALUE;
    PCMCB[1].InitOK = PCM_ENABLE_VALUE;
	PCMCBCreat(0);  //仅发送模块
	PCMCBCreat(1);
}

void *devm_map(unsigned long addr, int len, int *phandle)
{
    off_t offset;
    void *map_base;

    if ((*phandle = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
    {
	    printf("cannot open '/dev/mem'\n");
	    goto err_open;
    }

    /* offset for mmap() must be page aligned */
    offset = addr & ~(sysconf(_SC_PAGE_SIZE) - 1);

    map_base = mmap(NULL, len + addr - offset, PROT_READ | PROT_WRITE, MAP_SHARED, *phandle, offset);
    if (map_base == MAP_FAILED)
    {
	    printf("mmap failed\n");
	    goto err_mmap;
    }

    return map_base + addr - offset;
err_mmap:
	close(*phandle);
err_open:
	return NULL;
}

void PCMTest(int num)
{
    uint8_t RecData[PCM_BAG_SIZE];
    int rxret;

    memset(RecData, 0, PCM_BAG_SIZE);
    rxret = PCMReceive(num, RecData);
    if(rxret != 0)
    {
		printf("-------------------------\n");
		for(int i=0; i<PCM_BAG_SIZE; i++)
		{
			printf("%02x ", RecData[i]);
			if((i%16)==15) printf("\n");
		}
		printf("\n");
    }
    else
	    printf ("pcm_%d Not rx data\n", num);
}

//PCM接收中断服务
void *PCMReceiveISR_0(void *arg) //(uint32_t u32Port)
{
    uint16_t u16DataAddr = 0;
    uint16_t u16DataLen = 0;
    uint32_t i = 0;
    uint32_t Port = 0;//*(uint32_t *)arg;  hpk

    pthread_detach(pthread_self());

    //当前描述符指针
    //u16DesPCur = IO_READ16(PCMCB[Port].DesPAddr);
    //软件缓冲区未满，且当前描述符指针与记录描述符指针（描述符读指针）值不同时从逻辑缓冲区读取数据至软件缓冲区
    //每个循环读取一个描述符，读取一帧对应数据，描述符读空后退出
    //while((((PCMCB[Port].RBufWrite + 1) % PCM_RECEIVE_BUFF_SIZE) != PCMCB[Port].RBufRead)&&
    //    (IO_READ16(PCMCB[Port].DesPAddr) != PCMCB[Port].DesPRec))//&&
    while(1)
    {                       //固定寄存器地址0x16获取最新数据包首地址 = 描述符RAM读指针 0 4 8 ... 64
		if(IO_READ16(PCMCB[Port].DesPAddr) == PCMCB[Port].DesPRec)
		{
			usleep(100);
			continue;
		}

		//有数据但buffer队列满，则等下一个周期
		if(((PCMCB[Port].RBufWrite + 1) % PCM_RECEIVE_BUFF_SIZE) == PCMCB[Port].RBufRead)
		{
			usleep(100);
			continue;
		}
        //当前帧数据在逻辑接收RAM的起始地址，左移一位是因为1个16bit对应软件两个字节地址空间
        u16DataAddr = IO_READ16(PCMCB[Port].DesAddr + ((PCMCB[Port].DesPRec + PCM_DES_DATA_ADDR_WORD) << 2));
	//当前帧数据长度                                                     0x400                  0 4 8 ... 64
        u16DataLen  = IO_READ16(PCMCB[Port].DesAddr + ((PCMCB[Port].DesPRec + PCM_DES_COR_LEN_WORD) << 2));
        //只有低9位是长度
  //    u16DataLen &= PCM_DES_LEN_BIT;
		//记录的描述符指针移至下一个描述符
        PCMCB[Port].DesPRec = (PCMCB[Port].DesPRec + 4) % (PCM_RDES_BLOCK_RAM_LEN >> 2);

        if(u16DataLen <= PCM_BAG_SIZE)
        {
            for (i = 0; i < u16DataLen; i++)
            {
             //   PCMCB[u32Port].RBuf[PCMCB[u32Port].RBufWrite][i] = IO_READ16(PCMCB[u32Port].RAddr + ((u16DataAddr + i) << 2));
            	PCMCB[Port].RBuf[PCMCB[Port].RBufWrite][i] = IO_READ16(PCMCB[Port].RAddr + (((u16DataAddr + i) % 0x1000) << 2));
            }
	    //printf("--- PCM rx data(BagId=%d, len=%d) ---\n", PCMCB[Port].RBufWrite, u16DataLen);
	    //print_data((char *)&PCMCB[Port].RBuf[PCMCB[Port].RBufWrite][0], u16DataLen);
            //如果当前帧不够128字节也占用一个128字节数据项
            PCMCB[Port].RBufWrite = (PCMCB[Port].RBufWrite + 1) % PCM_RECEIVE_BUFF_SIZE;
        }
    }
	return NULL;
}

//PCM接收中断服务
void *PCMReceiveISR_1(void *arg) //(uint32_t u32Port)
{
    uint16_t u16DataAddr = 0;
    uint16_t u16DataLen = 0;
    uint32_t i = 0;
    uint32_t Port = 1;//*(uint32_t *)arg;  hpk

    pthread_detach(pthread_self());

    if (Port >= PCM_PORT_NUM)
    {
    	printf("PCMReceiveISR: u32Port=%d, PortMax=%d\n", Port, PCM_PORT_NUM-1);
        return NULL;
    }
    //当前描述符指针
    //u16DesPCur = IO_READ16(PCMCB[Port].DesPAddr);
    //软件缓冲区未满，且当前描述符指针与记录描述符指针（描述符读指针）值不同时从逻辑缓冲区读取数据至软件缓冲区
    //每个循环读取一个描述符，读取一帧对应数据，描述符读空后退出
    //while((((PCMCB[Port].RBufWrite + 1) % PCM_RECEIVE_BUFF_SIZE) != PCMCB[Port].RBufRead)&&
    //    (IO_READ16(PCMCB[Port].DesPAddr) != PCMCB[Port].DesPRec))//&&
    while(1)
    {
		if(IO_READ16(PCMCB[Port].DesPAddr) == PCMCB[Port].DesPRec)
		{
			usleep(100);
			continue;
		}

		//有数据但buffer队列满，则等下一个周期
		if(((PCMCB[Port].RBufWrite + 1) % PCM_RECEIVE_BUFF_SIZE) == PCMCB[Port].RBufRead)
		{
			usleep(100);
			continue;
		}

        //当前帧数据在逻辑接收RAM的起始地址，左移一位是因为1个16bit对应软件两个字节地址空间
        u16DataAddr = IO_READ16(PCMCB[Port].DesAddr + ((PCMCB[Port].DesPRec + PCM_DES_DATA_ADDR_WORD) << 2));

		//当前帧数据长度
        u16DataLen = IO_READ16(PCMCB[Port].DesAddr + ((PCMCB[Port].DesPRec + PCM_DES_COR_LEN_WORD) << 2));
        //只有低9位是长度
  //      u16DataLen &= PCM_DES_LEN_BIT;

        //printf("Rec=%X, Cur=%X, DAddr = %X\n", DesPRec, u16DesPCur, u16DataAddr);

		//记录的描述符指针移至下一个描述符
        PCMCB[Port].DesPRec = (PCMCB[Port].DesPRec + 4) % (PCM_RDES_BLOCK_RAM_LEN >> 2);

		//一帧最多128字节
        if(u16DataLen <= PCM_BAG_SIZE)
        {
            for (i = 0; i < u16DataLen; i++)
            {
             //   PCMCB[u32Port].RBuf[PCMCB[u32Port].RBufWrite][i] = IO_READ16(PCMCB[u32Port].RAddr + ((u16DataAddr + i) << 2));
            	PCMCB[Port].RBuf[PCMCB[Port].RBufWrite][i] = IO_READ16(PCMCB[Port].RAddr + (((u16DataAddr + i) % 0x1000) << 2));
            }
			//printf("--- PCM rx data(BagId=%d, len=%d) ---\n", PCMCB[Port].RBufWrite, u16DataLen);
			//print_data((char *)&PCMCB[Port].RBuf[PCMCB[Port].RBufWrite][0], u16DataLen);
            //如果当前帧不够128字节也占用一个128字节数据项
            PCMCB[Port].RBufWrite = (PCMCB[Port].RBufWrite + 1) % PCM_RECEIVE_BUFF_SIZE;
        }
    }

	return NULL;
}

//PCM发送，目前只有一个PCM接口，端口号固定为0
uint32_t PCMSend(uint32_t u32Port, uint8_t u8aSData[], uint32_t u32Len)
{
    uint32_t i = 0;

    if (u32Port >= PCM_PORT_NUM)
    {
        printf("PCMSend: PortMax = %d", PCM_PORT_NUM-1);
        return -1;
    }

    if (PCMCB[u32Port].InitOK != PCM_ENABLE_VALUE)
    {
        PCMInit(u32Port);
    }

    //单帧长度不能超过发送FIFO容量
    if (u32Len > PCM_TBUFF_LEN)
    {
        u32Len = PCM_TBUFF_LEN;
    }

    if (u32Len == 0)
    {
        return 0;
    }

    //semTake(PCMCB[u32Port].semT, 500);

    //判断发送FIFO剩余空间是否够容纳当前帧
    if (IO_READ16(PCMCB[u32Port].TUCAddr) > PCM_TBUFF_LEN - u32Len)
    {
        //taskDelay(2);
        usleep(2000);
    }

    for (i = 0; i < u32Len; i++)
    {
        IO_WRITE16(PCMCB[u32Port].TAddr, u8aSData[i]);
		usleep(1);
    }

    //数据完成通知逻辑接口可以开始发送了，逻辑会发送到发送FIFO全空为止
    IO_WRITE16(PCMCB[u32Port].CTAddr, PCM_CTRL_T_START_BIT);

	//semGive(PCMCB[u32Port].semT);

    return u32Len;
}

//PCM接收，从软件缓冲区读取数据至用户数据，按照当前协议，每帧固定128字节
uint32_t PCMReceive(uint32_t Port, uint8_t *DataBuf)
{
    if (Port >= PCM_PORT_NUM)
    {
        printf("PCMReceive: PortMax = %d", PCM_PORT_NUM-1);
        return 0;
    }

    if (PCMCB[Port].InitOK != PCM_ENABLE_VALUE)
    {
        PCMInit(Port);
    }
    //semTake(PCMCB[u32Port].semR, 100);
    //判断软件缓冲区是否为空
    if(PCMCB[Port].RBufRead != PCMCB[Port].RBufWrite)
    {
        memcpy(DataBuf, PCMCB[Port].RBuf[PCMCB[Port].RBufRead], PCM_BAG_SIZE);
		PCMCB[Port].RBufRead = (PCMCB[Port].RBufRead + 1) % PCM_RECEIVE_BUFF_SIZE;
        //semGive(PCMCB[u32Port].semR);
        return PCM_BAG_SIZE;
    }
    else
    {
        //semGive(PCMCB[u32Port].semR);
        return 0;
    }
}

void PCMInit(uint32_t Port)
{
    int ret;

    if (Port >= PCM_PORT_NUM)
    {
        printf("PCMInit: PortMax = %d", PCM_PORT_NUM-1);
        return ;
    }
//	enable(5, 0);

    //先初始化控制块本身，只会执行一次
    PCMCBCreat(Port);
    //semTake(PCMCB[u32Port].semT, 500);
    //semTake(PCMCB[u32Port].semR, 500);
    PCMCB[Port].DesPRec = 0;
    PCMCB[Port].initCnt = 0;
    PCMCB[Port].RBufWrite = 0;
    PCMCB[Port].RBufRead = 0;
	//复位PCM接口的收发模块
    IO_WRITE16(PCMCB[Port].CTAddr, PCM_CTRL_T_RESET_BIT | PCM_CTRL_R_RESET_BIT);
    //taskDelay(2);
    usleep(2000);

    if(Port == 0)
    {
		ret = pthread_create(&PCMCB[Port].rxThrd, NULL, PCMReceiveISR_0, NULL);
		if (ret != 0)
		{
			printf("Create PCMReceiveISR fail: %s\n", strerror(ret));
			PCMCB[Port].rxThrd = 0;
			return;
		}
		PCMCB[Port].InitOK = PCM_ENABLE_VALUE;
    }
    else if(Port == 1)
    {
		ret = pthread_create(&PCMCB[Port].rxThrd, NULL, PCMReceiveISR_1, NULL);
		if (ret != 0)
		{
			printf("Create PCMReceiveISR fail: %s\n", strerror(ret));
			PCMCB[Port].rxThrd = 0;
			return;
		}
		PCMCB[Port].InitOK = PCM_ENABLE_VALUE;
    }
    //semGive(PCMCB[Port].semR);
    //semGive(PCMCB[Port].semT);
    return;
}

//PCM控制块初始化
void PCMCBCreat(uint32_t Port)
{
    //taskLock();
    //纯软件部分，不对外通信，只能执行一次，防止反复生成信号量与管理线程
    if (PCMCB[Port].Enable != PCM_ENABLE_VALUE)
    {
        //PCMCB[Port].semT = semMCreate(EM_Q_PRIORITY);
        //PCMCB[Port].semR = semMCreate(EM_Q_PRIORITY);
        PCMCB[Port].RBufLock = 0;
        PCMCB[Port].Enable = PCM_ENABLE_VALUE;
        PCMCB[Port].Port = Port;
		//控制寄存器
        PCMCB[Port].CTAddr =   (uint32_t)PcmAddr + PCM_PORT_ADDR_LEN * Port + PCM_CTRL_REG;
		//发送寄存器
        PCMCB[Port].TAddr =    (uint32_t)PcmAddr + PCM_PORT_ADDR_LEN * Port + PCM_TDATA_REG;
		PCMCB[Port].STAddr =   (uint32_t)PcmAddr + PCM_PORT_ADDR_LEN * Port + PCM_STAT_REG;
        PCMCB[Port].TUCAddr =  (uint32_t)PcmAddr + PCM_PORT_ADDR_LEN * Port + PCM_TBUFF_USE_COUNT_REG;
		//接收寄存器
        PCMCB[Port].DesPAddr = (uint32_t)PcmAddr + PCM_PORT_ADDR_LEN * Port + PCM_RDES_BLOCK_POINT_REG;
        PCMCB[Port].DesAddr =  (uint32_t)PcmAddr + PCM_PORT_ADDR_LEN * Port + PCM_RDES_BLOCK_RAM_ADDR;
		PCMCB[Port].RAddr =    (uint32_t)PcmAddr + PCM_PORT_ADDR_LEN * Port + PCM_RBUFF_RAM_ADDR;
		PCMCB[Port].Frame_addr=(uint32_t)PcmAddr + PCM_PORT_ADDR_LEN * Port + PCM_frame_cnt;
#if 0
#ifdef PCM_INT_ENABLE
        //目前PCM使用轮询接收
        PCMCB[Port].semIntT = semBCreate(EM_Q_PRIORITY, SEM_EMPTY);
#else
        if (TaskIdPCMReceive == 0)
        {
            TaskIdPCMReceive = taskSpawn("taskPCMReceive", 84, 0, 0x1000, (FUNCPTR)taskPCMReceive, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
        }
#endif
#endif
    }
    //taskUnlock();
}

//代替中断用的轮询任务，PCM 2Mbps速率，写满逻辑收RAM至少需要4毫秒，每3毫秒读空一次不会丢数
void taskPCMReceive(void)
{
    uint32_t u32Port = 0;
    //taskDelay(3);
	usleep(3000);

    while(1)
    {
        for (u32Port = 0; u32Port < PCM_PORT_NUM; u32Port++)
        {
            if (PCMCB[u32Port].InitOK == PCM_ENABLE_VALUE)
            {
               // PCMReceiveISR(&u32Port);
            	;
            }
        }
        //taskDelay(3);
        usleep(3000);
    }
}

uint16_t IO_READ16(uint32_t addr)
{
    uint32_t data;
    data = *(uint32_t *)addr;
    return (uint16_t)(data&0xffff);

    //return *(uint16_t*)addr;
}

void IO_WRITE16(uint32_t addr, uint16_t value)
{
    uint32_t data = (uint32_t)value;
    data = data&0xffff;

    *(uint32_t *)addr = data;

    //*(uint16_t *)addr = value;
}

void print_data(char *data, int len)
{
    //printf("---- print_data function ----");
    for(int i=0; i<len; i++)
    {
	/* 每16个字节一行，并输出首地址 */
	if((i%16) == 0)
	{
		if(i>0)
		{
			printf("\n");
		}
		printf("<offset:%04x>  ", i);
	}

	/* 每8个字节增加一个空格 */
	if((i%16) == 8)
	{
		printf("  ");
	}

	/* 输出每个字节 */
	printf("%02x ", data[i]);

	if(i>=1023)
	{
		break;
	}
    }

    printf("\n");
}

//打印PCM接口状态
void PCMPrint(uint32_t u32Port)
{
    uint32_t i = 0;

//	printf("g_initCnt = %d, g_rxThrdCnt = %d\n", g_initCnt, g_rxThrdCnt);
    printf("PCM Port = %d\n", PCMCB[u32Port].Port);

    //控制和发送寄存器
    printf("PCM CTAddr(0x%08x) value = 0x%04X\n",
	    PCMCB[u32Port].CTAddr, IO_READ16(PCMCB[u32Port].CTAddr));
    printf("PCM TAddr(0x%08x) value = 0x%04X\n",
	    PCMCB[u32Port].TAddr, IO_READ16(PCMCB[u32Port].TAddr));
    printf("PCM STAddr(0x%08x) value = 0x%04X\n",
	    PCMCB[u32Port].STAddr, IO_READ16(PCMCB[u32Port].STAddr));
    printf("PCM TUCAddr(0x%08x) value = 0x%04X\n",
	    PCMCB[u32Port].TUCAddr, IO_READ16(PCMCB[u32Port].TUCAddr));

    //接收寄存器
    printf("PCM DesPAddr(0x%08x) value = 0x%04X\n",
    PCMCB[u32Port].DesPAddr, IO_READ16(PCMCB[u32Port].DesPAddr));
    printf("PCM DesAddr(0x%08x) value = 0x%04X\n",
	    PCMCB[u32Port].DesAddr, IO_READ16(PCMCB[u32Port].DesAddr));
    printf("PCM RAddr(0x%08x) value = 0x%04X\n",
	    PCMCB[u32Port].RAddr, IO_READ16(PCMCB[u32Port].RAddr));

    printf("PCM DesPRec = 0x%04X\n", PCMCB[u32Port].DesPRec);
    printf("PCM RBufWrite=%02X\n", PCMCB[u32Port].RBufWrite);
    printf("PCM RBufRead=%02X\n", PCMCB[u32Port].RBufRead);
    printf("PCM Des:\n");
    for (i = 0; i < (PCM_RDES_BLOCK_RAM_LEN >> 2); i++)
    {
        printf("D[%02X]=%04X ", i, IO_READ16(PCMCB[u32Port].DesAddr + (i << 2)));
	usleep(1);
        if (i % 4 == 3)
        {
            printf("\n");
        }
    }
    if (i % 4 != 0)
    {
        printf("\n");
    }
}

uint16_t PCM_frame_count(int port)
{
    uint16_t count = 0 ;
    if((port==0)||(port==1))
    {
	    count = IO_READ16(PCMCB[port].Frame_addr);
	    printf("PCM_%d recve frame count = %d\n", port, count);
    }
    else
	    printf("port invalid\n");
    return count ;
}

void PCM_frame_clear(int port)
{
    if((port==0)||(port==1))
    {
	    IO_WRITE16(PCMCB[port].Frame_addr, 0);
	    printf("PCM_%d frame reset, current count = %d\n", port, IO_READ16(PCMCB[port].Frame_addr));
    }
    else
	    printf("port invalid\n");
}

void sleep_ms(unsigned int secs)
{
	struct timeval tval;

	tval.tv_sec=secs/1000;
	tval.tv_usec=(secs*1000)%1000000;
	select(0,NULL,NULL,NULL,&tval);
}
